package main

import (
	"errors"
	"fmt"
	"net"
	"os"
	"smb-trans/app"
	"smb-trans/network"
	"strconv"
	"sync"
)

func main() {
	//path := "./logs/1/client_2.log"
	//content, _ := os.ReadFile(path)
	//fmt.Println(content, "===>")
	//common.TryFindHost(content)
	//return
	//server := tcpserver.TcpServer{}
	//server.OnMessage(func(connection net.Conn, message []byte) {
	//	fmt.Println(string(message))
	//})
	//server.OnError(func(err error) {
	//	fmt.Println(err)
	//})
	//server.Start(445, true)
	//fmt.Println("server start")
	//tcpserver:=net.Listen("")
	var tcpAddr *net.TCPAddr
	tcpAddr, _ = net.ResolveTCPAddr("tcp", "0.0.0.0:445")
	tcpListener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("start listening on tcp://0.0.0.0:445")
	_ = os.RemoveAll("./logs")
	_ = os.MkdirAll("./logs", 0777)
	//targetAddr := "172.16.20.235:445"

	transId := 0
	for {
		transId++
		tcpConn, err := tcpListener.AcceptTCP()
		if err != nil {
			continue
		}
		fmt.Println("new connection from", tcpConn.RemoteAddr())
		go startProcess(tcpConn, transId)

	}
}

func startProcess(tcpConn net.Conn, transId int) {
	if true {
		localConn, remoteConn, err := tryGetConnAndTargetConn(tcpConn)
		if err != nil {
			fmt.Println(err)
			return
		}
		//buffer := make([]byte, 1024)
		//n, _ := localConn.Read(buffer)
		//_, err = remoteConn.Write(buffer[0:n])
		//if err != nil {
		//	fmt.Println(err, "firsterr------------------->")
		//}
		//read, err := remoteConn.Read(buffer)
		//if err != nil {
		//	return
		//}
		//fmt.Println(buffer[0:read], "first read----------------->")

		//return

		go relay(localConn, remoteConn, strconv.Itoa(transId))
	} else {
		localConn := tcpConn
		remoteConn, err := net.Dial("tcp", "172.16.20.235:445")
		if err == nil {
			go relay(localConn, remoteConn, strconv.Itoa(transId))
		}
	}

}

//lds12345

func tryGetConnAndTargetConn(tcpConn net.Conn) (net.Conn, net.Conn, error) {
	hostConfig := map[string]string{
		"smblocal.playnas.com": "172.16.20.235:445",
		"smbtest.playnas.com":  "172.16.10.131:445",
		"smb-yu.playnas.com":   "172.16.20.19:445",
	}
	var localConn net.Conn
	var targetAddr string
	//defer tcpConn.Close()
	retryIndex := 0
	for {
		retryIndex++
		if retryIndex >= 3 {
			return localConn, tcpConn, errors.New("failed to get host")
		}
		conn, s, err := app.FindAddrHandler(tcpConn, retryIndex)
		if err != nil {
			fmt.Println(err)
			continue
		}
		if s == "" {
			_, _ = tcpConn.Write(getFirstResponsePackage())
			continue
		} else {
			localConn = conn
		}

		if addr, ok := hostConfig[s]; !ok {
			fmt.Println("寻址失败:"+s, "-------------------->")
			targetAddr = "172.16.20.235:445"
			break
			//continue
		} else {
			fmt.Println(fmt.Sprintf("寻址成功:%d:%s ", retryIndex, s))
			targetAddr = addr
			break
		}
	}
	fmt.Println("targetAddr:", targetAddr)
	remoteConn, err := net.Dial("tcp", targetAddr)
	if err == nil {
		if retryIndex != 1 {
			fmt.Println(getFirstRequestPackage(), "%%%%%%%%%")
			_, _ = remoteConn.Write(getFirstRequestPackage())
			buff := make([]byte, 1024)
			_, err = remoteConn.Read(buff)
			if err != nil {
				fmt.Println("failed to read"+err.Error(), "--------->")
			}
			fmt.Println(string(buff), "first read2222222222------------------------->")
		}

	}
	return localConn, remoteConn, err
}

func getFirstResponsePackage() []byte {
	file, err := os.ReadFile("./package/first_response.example")
	if err != nil {
		return nil
	}
	return file
}

func getFirstRequestPackage() []byte {
	file, err := os.ReadFile("./package/first_request.example")
	if err != nil {
		return nil
	}
	return file
}

func relay(left, right net.Conn, transactionId string) {
	//logger := log.FileLoger{
	//	LogPath: "./logs/" + transactionId + "_",
	//}
	bufferDir := "./logs/" + transactionId + "/"
	_ = os.MkdirAll(bufferDir, 0777)
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer func() {
			_ = right.Close()
			wg.Done()
		}()
		if err := network.IoCopy(right, left, func(content []byte, readSecond int) {
			//logger.Debug(fmt.Sprintf("server read %d content: %s", readSecond, string(content)))
			//_ = os.WriteFile(fmt.Sprintf("%s_%d.log", bufferDir+"server", readSecond), content, 0777)
		}); err != nil {
			fmt.Printf("left[TCP] %v", err)
		}
	}()
	go func() {
		defer func() {
			_ = left.Close()
			wg.Done()
		}()
		if err := network.IoCopy(left, right, func(content []byte, readSecond int) {
			//_ = os.WriteFile(fmt.Sprintf("%s_%d.log", bufferDir+"client", readSecond), content, 0777)
			//logger.Debug(fmt.Sprintf("client read %d content: %s", readSecond, string(content)))
		}); err != nil {
			fmt.Printf("right[TCP] %v", err)
		}
	}()
	wg.Wait()
}
